import { AfterViewInit, ChangeDetectorRef, OnInit, ViewChild } from '@angular/core';
import { TableComponent } from '../../common/table/table.component';
import { Query } from '../http/query';
import { OnReuseDestroy, OnReuseInit } from '../reuse-hooks';
import { TableColumnCustomService } from '../service/table-column-custom.service';
import { detectCallSuperMethod } from '../tools';
import { BaseView } from './base-view';


export class BzQueryView<U, B, S> extends BaseView<U, B, S> implements AfterViewInit, OnInit, OnReuseInit, OnReuseDestroy {

  @ViewChild('form', { static: false }) formComponent: any;
  @ViewChild('dataGrid', { static: false }) dataGrid: TableComponent<U, B, S>;
  query: Query<U> = new Query();
  /** 当前查询表单校验是否有异常 */
  formMainValidateError: boolean;
  /** 查询参数 */
  queryParams: any = {};
  tableColumnCustomService: TableColumnCustomService<U, B, S>;

  private _ngOnInit = false;
  private _ngAfterViewInit = false;
  private _reuseOnDestroy = false;
  private _reuseOnInit = false;

  constructor() {
    super();
    const injector = (<any>window)._moduleRef.injector;
    this.tableColumnCustomService = injector.get(TableColumnCustomService);
    this.ngZone.runOutsideAngular(() => {
      setTimeout(() => {
        if (!this._ngOnInit) {
          this.loggerService.error(new Error('"super.ngOnInit()" Not Implemented ---> ' + this.constructor.name));
        }
        if (!this._ngAfterViewInit) {
          this.loggerService.error(new Error('"super.ngAfterViewInit()" Not Implemented ---> ' + this.constructor.name));
        }
      }, 3000);
    });

    if (!detectCallSuperMethod(this, 'reuseOnInit')) {
      this.loggerService.error(new Error('"super.reuseOnInit()" Not Implemented ---> ' + this.constructor.name));
    }
    if (!detectCallSuperMethod(this, 'reuseOnDestroy')) {
      this.loggerService.error(new Error('"super.reuseOnDestroy()" Not Implemented ---> ' + this.constructor.name));
    }
  }

  ngOnInit(): void {
    this._ngOnInit = true;
    if (!this.queryParams) {
      this.loggerService.error(new Error('queryParams is empty ---> ' + this.constructor.name));
    }

    // 是否提交过数据
    this.queryParams._submitted = false;
    // 数据是否在发送中
    this.queryParams._submitting = false;
  }

  ngAfterViewInit(): void {
    this._ngAfterViewInit = true;
    if (!this.dataGrid) {
      this.loggerService.error(new Error('no bzTable ---> ' + this.constructor.name));
    }
    this.dataGrid.setBzFrontPagination(false);
    this.subscribes();
    this.tableColumnCustomService.columnCustom(this.dataGrid);
  }



  onQuery(focusToFirstPage = true) {
    if (!this.queryParams._submitted) {
      this.queryParams._submitted = true;

      // 跨过一次脏值检查来保证表单的isValid实时性
      setTimeout(() => {
        this.onQuery();
      }, 300);
      return;
    }

    if (this.formComponent && !this.formComponent.isValid) {
      this.formMainValidateError = true;
      this.postInvalid();
      return;
    }
    this.formMainValidateError = false;

    if (focusToFirstPage) {
      this.dataGrid.bzPageIndex = 1;
      this.query.page = {
        size: this.dataGrid.bzPageSize,
        start: 0,
        skip: 0
      };
    }
    this.initDataStore();
  }

  reuseOnDestroy(): void {
    this._reuseOnDestroy = true;
    this._reuseOnInit = false;
  }

  reuseOnInit(): void {
    this._reuseOnInit = true;
    this._reuseOnDestroy = false;
  }

  /** 子类需要重写父类的方法 */
  protected postInvalid() {
  }

  /** 子类可以重写父类的实现，返回自己的查询结果 */
  protected preLoad(loadOptions?: any): Promise<any> | void {
  }

  /** 子类可以重写父类的实现，处理服务器返回的数据 */
  protected postLoad(res: any): any {
    return res;
  }

  /** 子类可以重写父类的实现，返回自己的查询项内容 */
  protected parseQueryParams(loadOptions?: any): any {
    return this.serializeData(this.queryParams);
  }

  private subscribes() {
    this.dataGrid.bzPageIndexChange.subscribe((e) => {
      this.query.page = {
        size: this.dataGrid.bzPageSize,
        start: this.dataGrid.bzPageSize * (e - 1),
        skip: this.dataGrid.bzPageSize * (e - 1)
      };
      this.initDataStore();
    });
    this.dataGrid.bzPageSizeChange.subscribe((e) => {
      this.onQuery();
    });
    this.dataGrid.bzSortChange.subscribe((e: { key: string, value: string }) => {
      const sort = {
        field: e.key,
        type: e.value === 'ascend' ? 'asc' : 'desc'
      };
      if (this.query.sorts !== undefined && Array.isArray(this.query.sorts) && this.query.sorts.length > 0 && this.query.sorts.find(item => item.field === sort.field) !== undefined) {
        this.query.sorts[this.query.sorts.findIndex((item) => item.field === sort.field)] = { ...sort };
        this.dataGrid.bzPageIndex = 1;
        this.initDataStore();
      } else {
        const list = [...this.dataGrid.listOfData];
        this.dataGrid.listOfData = list.sort((a, b) => e.value === 'ascend' ? a[e.key] > b[e.key] ? 1 : -1 : b[e.key] > a[e.key] ? 1 : -1);
      }
    });
  }

  private initDataStore() {
    this.query.params = this.parseQueryParams();
    const promise = this.preLoad();
    if (promise && typeof promise.then === 'function') {
      promise.then(res => {
        const _res = this.postLoad(res);
        this.dataGrid.listOfData = _res.data || [];
        this.dataGrid.setBzTotal(_res.totalCount || 0);
        this.dataGrid.asyncNoResult = this.dataGrid.listOfData.length === 0 ? true : false;
      });
      return promise;
    }
    this.queryParams._submitting = true;
    this.dataGrid.bzLoading = true;
    this.httpService.query(this.query.url, this.query, this.query.httpOptions).then((res) => {
      const _res = this.postLoad(res);
      this.dataGrid.listOfData = _res.data.items || [];
      this.dataGrid.setBzTotal(_res.data.count || 0);
      this.dataGrid.asyncNoResult = this.dataGrid.listOfData.length === 0 ? true : false;
    }).catch((res) => {
      this.dataGrid.listOfData = [];
      this.dataGrid.setBzTotal(0);
      this.dataGrid.asyncNoResult = true;
    }).finally(() => {
      this.queryParams._submitting = false;
      this.dataGrid.bzLoading = false;
    });
  }

}
